#!/usr/bin/env python
# -*- coding: utf-8 -*



import logging
log = logging.getLogger("util")

import time

try:
    from functools import partial
except ImportError:
    log.warning("Python 2.5 should be used. Overriding partial")
    class partial:
        """ Partial implementation for python 2.4 - "curry" """
        def __init__(self, fun, *args, **kwargs):
            self.fun = fun
            self.pending = args[:]
            self.kwargs = kwargs.copy()

        def __call__(self, *args, **kwargs):
            if kwargs and self.kwargs:
                kw = self.kwargs.copy()
                kw.update(kwargs)
            else:
                kw = kwargs or self.kwargs

            return self.fun(*(self.pending + args), **kw)

class MWT(object):
    """Memoize With Timeout"""
    _caches = {}
    _timeouts = {}

    def __init__(self,timeout=5):
        self.timeout = timeout

    def collect(self):
        """Clear cache of results which have timed out"""
        for func in self._caches:
            cache = {}
            for key in self._caches[func]:
                if (time.time() - self._caches[func][key][1]) < self._timeouts[func]:
                    cache[key] = self._caches[func][key]
            self._caches[func] = cache

    def __call__(self, f):
        self.cache = self._caches[f] = {}
        self._timeouts[f] = self.timeout

        def func(*args, **kwargs):
            kw = kwargs.items()
            kw.sort()
            key = (args, tuple(kw))
            try:
                v = self.cache[key]
                if (time.time() - v[1]) > self.timeout:
                    raise KeyError
            except KeyError:
                v = self.cache[key] = f(*args,**kwargs),time.time()
            return v[0]
        func.func_name = f.func_name

        return func
